<template>
  <view class="container">
    <canvas
        class="scene"
        type="2d"
        id="cvScene"
        disable-scroll="true"
        @touchstart="handleTouchStart"
        @touchmove="handleTouchMove"
        @touchend="handleTouchEnd"
    ></canvas>
    <button class="btn select" @click="handDrawing">选区</button>
    <button class="btn camera" @click="onCamera">拍照</button>
    <button class="btn zoom-in" @click="onZoomIn">放大</button>
    <button class="btn zoom-out" @click="onZoomOut">缩小</button>
    <button class="btn cut" @click="onCut">裁剪</button>
    <image class="img-display" :src="tmpImage" mode="aspectFit"></image>
  </view>
</template>

<script>
import CanvasScene from "@/utils/canvas_scene";

export default {
  name: 'Index',
  data() {
    return {
      scene: null,
      canvasElement: null,
      fingers: 1, // 手指个数
      isDrawing: false, // 是否在绘制
      handDrawnId: null, // 手绘节点
      startPoint: null, // 绘制起点
      tmpImage: null
    }
  },
  created() {
  },
  mounted() {
    // 初始化
    this.initialize()
  },
  methods: {
    initialize() {
      const query = uni.createSelectorQuery().in(this)
      query.select("#cvScene").fields({node: true, size: true, rect: true}, (result) => {
        this.canvasElement = result
        const options = {
          element: this.canvasElement,
          pixelRatio: uni.getSystemInfoSync().pixelRatio, // 像素比（高像素比可以解决高清屏幕模糊问题）
          scale: 1,
          minScale: 0.1,
          maxScale: 2
        }
        this.scene = new CanvasScene(options)
        this.scene.resetEvents()
        this.onAddSceneEvents()
        this.scene.clear()
        this.scene.draw()
      }).exec()
    },
    onAddSceneEvents() {
      this.scene.on('touchstart', this.onTouchStart)
      this.scene.on('touchmove', this.onTouchMove)
      this.scene.on('touchend', this.onTouchEnd)
      this.scene.on('component:selected', this.onComponentSelected)
      this.scene.on('component:unselected', this.onComponentUnselected)
    },
    handleTouchStart(e) {
      this.scene.onTouchStart(e)
    },
    handleTouchMove(e) {
      this.scene.onTouchMove(e)
    },
    handleTouchEnd(e) {
      this.scene.onTouchEnd(e)
    },
    onTouchStart(e) {
      // console.log("触摸开始", e)
      this.startPoint = e.point
      this.handDrawnId = `Hand-${+new Date()}`
      this.fingers = e.event.touches.length
    },
    onTouchMove(e) {
      // console.log("触摸移动", e)
      if (this.fingers !== 1 || !this.isDrawing) return
      const sp = this.startPoint
      const mp = e.point
      // 两点距离小于5，不进行绘制
      if (Math.abs(mp.x - sp.x) <= 5 || Math.abs(mp.y - sp.y) <= 5) return
      // 先移除在绘制
      this.scene.removeComponent(this.handDrawnId)
      this.scene.draw()
      const opt = {
        id: this.handDrawnId, points: [sp, {x: mp.x, y: sp.y}, mp, {x: sp.x, y: mp.y}],
        style: {lineWidth: 2, fillStyle: 'rgba(255,255,255,.4)', strokeStyle: 'rgba(0,0,0,.3)'}
      }
      this.scene.drawShape(opt)
    },
    onTouchEnd(e) {
      // console.log("触摸结束", e)
      if (!this.isDrawing) return
      this.scene.components.forEach(component => {
        if (component.id === this.handDrawnId) {
          component.style.strokeStyle = '#8aff01'
          component.selected = true
          this.handDrawing()
        } else {
          component.style.strokeStyle = '#ffffff60'
          component.selected = false
        }
      })
      this.scene.draw()
    },
    onComponentSelected(component) {
      if (this.isDrawing) return
      if (!component) return
      // console.log("选中了", component)
      component.style.strokeStyle = '#8aff01'
      this.scene.draw()
    },
    onComponentUnselected(component) {
      if (this.isDrawing) return
      if (!component) return
      component.style.strokeStyle = '#ffffff60'
      this.scene.draw()
    },
    handDrawing() {
      this.isDrawing = !this.isDrawing
      this.scene.canDrag = !this.isDrawing
    },
    onZoomIn() {
      this.scene.zoomIn()
    },
    onZoomOut() {
      this.scene.zoomOut()
    },
    onCamera() {
      this.scene.clear()
      uni.chooseMedia({
        count: 1,
        mediaType: ['image'],
        sourceType: ['camera'],
        sizeType: ['original'],
        camera: 'back',
        success: (result) => {
          const imageUrl = result.tempFiles[0].tempFilePath
          uni.getImageInfo({
            src: imageUrl,
            success: (res) => {
              this.scene.drawImage({
                points: [{x: 0, y: 0}],
                style: {
                  image: imageUrl,
                  width: res.width,
                  height: res.height
                }
              })
            },
            fail(reason) {
              console.log(reason)
            }
          })
        }
      })
    },
    onCut() {
      const comp = this.scene.getSelectedComponent()
      if (comp) {
        // console.log(comp)
        const { pixelRatio, scale, translate } = this.scene
        let x = (comp.boundingRect.tl.x * scale + translate.x)
        let y = (comp.boundingRect.tl.y * scale + translate.y)
        let destWidth = (comp.boundingRect.tr.x - comp.boundingRect.tl.x) * scale
        let destHeight = (comp.boundingRect.bl.y - comp.boundingRect.tl.y) * scale
        this.scene.removeComponent(comp.id)
        // console.log("剪切信息:", x, y, destWidth, destHeight)
        this.scene.draw(() => {
          uni.canvasToTempFilePath({
            canvas: this.scene.canvas,
            x: x / pixelRatio,
            y: y / pixelRatio,
            width: destWidth / pixelRatio,
            height: destHeight / pixelRatio,
            destWidth: destWidth,
            destHeight: destHeight,
            fileType: 'png',
            quality: 1.0,
            success: (res) => {
              // console.log(res)
              this.tmpImage = res.tempFilePath
            },
            fail: (err) => {
              console.error(err)
            }
          })
        })
      }
    }
  }
}
</script>

<style>
.container {
  position: relative;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.scene {
  position: absolute;
  top: 0;
  left: 0;
  width: 280px;
  height: 60vh;
}

.btn {
  position: fixed;
  right: 12px;
  width: auto;
  height: 48px;
  border-radius: 30%;
}

.btn.camera {
  top: 12px;
}

.btn.select {
  top: 72px;
}

.btn.zoom-in {
  top: 132px
}

.btn.zoom-out {
  top: 192px
}

.btn.cut {
  top: 252px
}

.img-display {
  position: absolute;
  top: 61vh
}
</style>